﻿using System.Windows.Input;
using SimpleTool.Base;
using System.Management;
using SimpleTool.Server;
using Serilog;
using static SimpleTool.SerialTool.SerialControl.ConfigSectionModel;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Threading;
using static SimpleTool.SerialTool.SerialControl.CommandSectionModel;
using System.IO.Ports;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using SimpleTool.TransformComponent;
using System.CodeDom.Compiler;
using Supabase.Gotrue;
using System.Xml.Linq;
using OfficeOpenXml;
using System.Data.Common;
using System.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using SimpleTool.ActivityUnit;
using System.Text.Json;
using static SimpleTool.ActivityUnit.ActivitySectionModel;
using System.Text.RegularExpressions;
using DynamicData;
using System.Security.Cryptography;
using Supabase.Postgrest.Attributes;
using System.Reflection;
using System.Threading.Tasks;
using System.Text;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Engineering;
using System.Windows.Media.Media3D;
using System.Windows.Automation.Peers;

namespace SimpleTool.SerialTool.SerialControl
{

    public class SerialViewModel : Notify
    {
        private readonly DispatcherTimer LoaclDBTimer = new();
        private readonly DispatcherTimer CloudDBTimer = new();
        private readonly int DBconnectTimeOut = 10000;
        private readonly Stopwatch DBconnectWatch = Stopwatch.StartNew();
        private readonly ConditionalWeakTable<DispatcherTimer, ConnectFlag> DBComplateKeyValuePairs = [];

        public event EventHandler<CommandChangeEventHandle>? CommandChange;

        public class CommandChangeEventHandle : EventArgs
        {
            public AlterCommandStruct data;

            public CommandChangeEventHandle(AlterCommandStruct editInfo)
            {
                data = editInfo;
            }
        }

        public SerialViewModel(ISerialServer serialseriver,
                               IDirFileServer dirfileserver,
                               IDatabaseServer databaseserver,
                               IDenCryptoGraphic cryptserver,
                               IPowerPlant powerServer,
                               IActivityDetetorAssist Q)
        {
            SerialServer = serialseriver;

            DirFileServer = dirfileserver;

            DatabaseSeriver = databaseserver;

            PowerPlantServer = powerServer;

            CryptoGraphicSeriver = cryptserver;

            i = Q;

            LoaclDBTimer.Interval = new TimeSpan(50);
            CloudDBTimer.Interval = new TimeSpan(1000);
            ConnectFlag LocaldBConnectFlag = DBComplateKeyValuePairs.GetOrCreateValue(LoaclDBTimer);
            if (!LocaldBConnectFlag.IsConnected)
            {
                WeakEventManager<DispatcherTimer, EventArgs>.AddHandler(LoaclDBTimer, nameof(DispatcherTimer.Tick), LocalReadyWork);
                LocaldBConnectFlag.IsConnected = true;
            }

            ConnectFlag ClouddBConnectFlag = DBComplateKeyValuePairs.GetOrCreateValue(CloudDBTimer);
            if (!ClouddBConnectFlag.IsConnected)
            {
                WeakEventManager<DispatcherTimer, EventArgs>.AddHandler(CloudDBTimer, nameof(DispatcherTimer.Tick), CloudReadyWork);
                ClouddBConnectFlag.IsConnected = true;
            }

            WeakReferenceMessenger.Default.Register<MvvmMessage>(this, MvvmMessageProcessPlant);

            DBconnectStart();

            ModelUpdate();

            string card = "[20:58:42] \r\n[270] \"LPCD IRQ RXCHANGE SET!\"\r\n[271] \"lpcd_delta2 = 0x0 , lpcd_delta1 = 0xc6 \\r\\n\"\r\n[272] \"-> TYPE_A Card Detected!\"\r\n[273] \"-> ATQA = \"0400\r\n[274] \"; UID = \"1D0699E0\r\n[275] \"; S\r\n[20:58:42] \r\n[270] \"LPCD IRQ RXCHANGE SET!\"\r\n[271] \"lpcd_delta2 = 0x0 , lpcd_delta1 = 0xc6 \\r\\n\"\r\n[272] \"-> TYPE_A Card Detected!\"\r\n[273] \"-> ATQA = \"0400\r\n[274] \"; UID = \"1D0699E0\r\n[275] \"; SAK = \"08";
            //Logger.DebudElite(Regex.Match(card, "(?-i)UID\\s*=\\s*\\W*([0-9a-zA-Z]+)\\W*").Groups[1].Value);
        }

        IActivityDetetorAssist i;

        public ISerialServer SerialServer;

        public IDirFileServer DirFileServer;

        public IDatabaseServer DatabaseSeriver;

        public IDenCryptoGraphic CryptoGraphicSeriver;

        public IPowerPlant PowerPlantServer;

        private PublicSectionModel? PublicTemplateModel;

        private ConfigSectionModel? ConfigTemplateModel;

        private CommandSectionModel? CommandTemplateModel;

        private readonly ILogger Logger = Log.ForContext<SerialViewModel>();

        public PublicSectionModel HoldPublicSectionModel
        {
            set
            {
                PublicTemplateModel = value;
                propertyChangeSend(nameof(HoldPublicSectionModel));
            }
            get
            {
                PublicTemplateModel ??= new PublicSectionModel();
                return PublicTemplateModel;
            }
        }

        public ConfigSectionModel HoldConfigSectionModel
        {
            set
            {
                ConfigTemplateModel = value;
                propertyChangeSend(nameof(HoldConfigSectionModel));
            }
            get
            {
                ConfigTemplateModel ??= new ConfigSectionModel();
                return ConfigTemplateModel;
            }
        }

        public CommandSectionModel HoldCommandSectionModel
        {
            set
            {
                CommandTemplateModel = value;
                propertyChangeSend(nameof(HoldCommandSectionModel));
            }
            get
            {
                CommandTemplateModel ??= new CommandSectionModel();
                return CommandTemplateModel;
            }
        }

        public ICommand SerialConnectCommand
        {
            set
            {
                HoldConfigSectionModel.Srilconnect = value;
            }
            get
            {
                HoldConfigSectionModel.Srilconnect ??= new EasyCommand(ConnectExcuteEvent, bool () => { return true; });
                return HoldConfigSectionModel.Srilconnect;
            }
        }

        public ICommand AtrributeChangeCommand
        {
            set
            {
                HoldConfigSectionModel.AtrributeChangeCommand = value;
            }
            get
            {
                HoldConfigSectionModel.AtrributeChangeCommand ??= new EasyCommand(ConfigProperyChangeEvent, bool () => { return true; });
                return HoldConfigSectionModel.AtrributeChangeCommand;
            }
        }

        public ICommand CommandAddedCommand
        {
            set
            {
                HoldCommandSectionModel.CommandAddedCommand = value;
            }
            get
            {
                HoldCommandSectionModel.CommandAddedCommand ??= new EasyCommand(CommandAddedEvent, bool () => { return true; });
                return HoldCommandSectionModel.CommandAddedCommand;
            }
        }

        public ICommand CommandTakeCommand
        {
            set
            {
                HoldCommandSectionModel.CommandTakeCommand = value;
            }
            get
            {
                HoldCommandSectionModel.CommandTakeCommand ??= new EasyCommand(CommandTakeEvent, bool () => { return true; });
                return HoldCommandSectionModel.CommandTakeCommand;
            }
        }

        public ICommand CommandIndexCommand
        {
            set
            {
                HoldCommandSectionModel.CommandIndexCommand = value;
            }
            get
            {
                HoldCommandSectionModel.CommandIndexCommand ??= new EasyCommand(CommandIndexEvent, bool () => { return true; });
                return HoldCommandSectionModel.CommandIndexCommand;
            }
        }

        public ICommand CommandWriteCommand
        {
            set
            {
                HoldCommandSectionModel.CommandWriteCommand = value;
            }
            get
            {
                HoldCommandSectionModel.CommandWriteCommand ??= new EasyCommand(CommandWriteEvent, bool () => { return true; });
                return HoldCommandSectionModel.CommandWriteCommand;
            }
        }

        public ICommand CommandModeCommand
        {
            set
            {
                HoldCommandSectionModel.CommandModeCommand = value;
            }
            get
            {
                HoldCommandSectionModel.CommandModeCommand ??= new EasyCommand(CommandModeEvent, bool () => { return true; });
                return HoldCommandSectionModel.CommandModeCommand;
            }
        }

        public ICommand CommandEditCommand
        {
            set
            {
                HoldCommandSectionModel.CommandEditCommand = value;
            }
            get
            {
                HoldCommandSectionModel.CommandEditCommand ??= new EasyCommand(CommandEditEvent, bool () => { return true; });
                return HoldCommandSectionModel.CommandEditCommand;
            }
        }

        // 连接按钮启用标识
        public bool PublicConnectEnable
        {
            set
            {
                HoldConfigSectionModel.PublicConnectEnable = value;
                propertyChangeSend(nameof(PublicConnectEnable));
            }
            get
            {
                return HoldConfigSectionModel.PublicConnectEnable;
            }
        }

        public static void MvvmMessageProcessPlant(object recipient, MvvmMessage message)
        {
            SerialViewModel self = (SerialViewModel)recipient;
            switch (message.Type)
            {
                case MvvmMessage.MvvmType.Command_EditInfoSend:
                    self.CommandChangeEvent(message);
                    break;
            }
        }

        //指令新增
        public void CommandAddedEvent(object? param)
        {
            CommandStruct NewListItem = new ("", 0, "");
            HoldCommandSectionModel.CommandListItems.Add(NewListItem);
            HoldCommandSectionModel.CurrentItem = NewListItem;
            ModelUpdate(1);
        }

        //指令删除
        public async void CommandTakeEvent(object? param)
        {
            try
            {
                if (DatabaseSeriver.GetIdentify())
                {
                    if (DatabaseSeriver.GetCloudDB() is not null and Supabase.Client CloudDB)
                    {
                        List<string> commandTakes = [.. HoldCommandSectionModel.CommandSelectionsCache.Select(x => x.Command)];

                        await CloudDB.From<SerialCommand>()
                              .Filter("command_name", Supabase.Postgrest.Constants.Operator.In, commandTakes)
                              .Delete();

                        foreach (var _struct in HoldCommandSectionModel.CommandSelectionsCache)
                        {
                            HoldCommandSectionModel.CommandListItems.Remove(_struct);
                            ModelUpdate();
                        }
                    }
                }
                else
                {
                    List<string> commandTakeSqls = [.. HoldCommandSectionModel.CommandSelectionsCache.Select(x=>
                                                   $"DELETE FROM serial_command WHERE command_name='{x.Command}'")];
                    List<CommandStruct> backDatas = [.. HoldCommandSectionModel.CommandSelectionsCache];

                    var deleteResult = await DatabaseSeriver.LocalDBQuery(commandTakeSqls);
                    if (deleteResult.ErrorHint is null)
                    {
                        foreach (var _struct in HoldCommandSectionModel.CommandSelectionsCache)
                        {
                            HoldCommandSectionModel.CommandListItems.Remove(_struct);
                            ModelUpdate();
                        }
                    }
                    HoldCommandSectionModel.CommandSelectionsCache.Clear();
                }
            } 
            catch (Exception error)
            {
                Logger.ErrorElite(error.Message);
            }
        }

        // 指令索引更改，获取更改指令集合
        public void CommandIndexEvent(object? param)
        {

            if (param != null && param is List<CommandStruct> commandStructs)
            {
                HoldCommandSectionModel.CommandSelectionsCache = [..commandStructs];
                ModelUpdate(1);
            }
        }

        // 指令编辑信息发送至OverView展示
        public void CommandEditEvent(object? param)
        {
            if (param is not null and AlterCommandStruct EditInfo)
            {
                WeakReferenceMessenger.Default.Send<MvvmMessage>(new MvvmMessage(MvvmMessage.MvvmType.Command_EditInfoGet, EditInfo));
            }
        }

        // 单个指令更新
        public async void CommandChangeEvent(MvvmMessage message)
        {
            
            if (message.MsgBody is not null and AlterCommandStruct CommandAlterCache &&
                CommandAlterCache.AlterIndex != -1 &&
                HoldCommandSectionModel.CommandListItems.Count > CommandAlterCache.AlterIndex)
            {
                int ChangeIndex = CommandAlterCache.AlterIndex;
                string OldCommand = HoldCommandSectionModel.CommandListItems[ChangeIndex].Command;
                string NewCommand = CommandAlterCache.AlterCommand.Command;
                int NewDuration = CommandAlterCache.AlterCommand.Duration;
                string NewAlias = CommandAlterCache.AlterCommand.Alias;

                try
                {
                    if (DatabaseSeriver.GetIdentify())
                    {
                        if (DatabaseSeriver.GetCloudDB() is not null and Supabase.Client CloudDB)
                        {
                            Action<double, string> _process = CustomMessageBox.Show(0, 3, 0);

                            SerialCommand data = new()
                            {
                                Commandname = NewCommand,
                                Commandalias = NewAlias,
                                Commandinterval = NewDuration.GetSafetyChar()
                            };
                            var QueryResponse = await CloudDB.From<SerialCommand>()
                                .Where(x => x.Commandname == OldCommand)
                                .Get();

                            Logger.DebudElite();

                            _process.Invoke(1, "执行中...");

                            DatabaseSeriver.CloudAnchorChannel<SerialCommand>(async () =>
                            {
                                int retryCount = 0;
                                while (retryCount < 4)
                                {
                                    var QueryResponse = await CloudDB.From<SerialCommand>()
                                                        .Where(x => x.Commandname == NewCommand)
                                                        .Get();

                                    if (QueryResponse.Model is not null && QueryResponse.Model.Commandname == NewCommand)
                                    {
                                        _process.Invoke(3, "执行完成");
                                        break;
                                    }
                                    else
                                    {
                                        _process.Invoke(1, "执行失败");
                                        retryCount++;
                                        await Task.Delay(300);
                                        continue;
                                    }
                                }
                            });

                            if (QueryResponse.ResponseMessage is not null && 
                                QueryResponse.ResponseMessage.IsSuccessStatusCode && 
                                QueryResponse.Model is not null)
                            {
                                await CloudDB.From<SerialCommand>()
                                    .Set(x => x.Commandinterval, NewDuration.GetSafetyChar())
                                    .Set(x => x.Commandalias, NewAlias)
                                    .Set(x => x.Commandname, NewCommand)
                                    .Where(x => x.Commandname == OldCommand)
                                    .Update();

                                _process.Invoke(2, "执行中...");

                                Logger.DebudElite(OldCommand, NewCommand);
                            }
                            else
                            {
                                if (!string.IsNullOrEmpty(NewCommand))
                                {
                                    await CloudDB.From<SerialCommand>().Insert(data);
                                    _process.Invoke(2, "执行中...");
                                }
                            }
                        }
                    }

                    else
                    {
                        string queryCommandSql = $"SELECT * FROM serial_command WHERE command_name='{OldCommand}'";

                        string updateCommandSql = "UPDATE serial_command SET " +
                                                   $"command_name = '{NewCommand}'," +
                                                   $"command_interval = '{NewDuration}', " +
                                                   $"command_alias = '{NewAlias}' " +
                                                   $"WHERE command_name='{OldCommand}'";

                        string insertCommandSql = $"INSERT INTO serial_command VALUES(" +
                                                  $"'{NewCommand}'," + $"'{NewAlias}'," + $"'{NewDuration}')";

                        if (await DatabaseSeriver.LocalDBQueryFree(queryCommandSql) is var queryResult && queryResult != null)
                        {
                            bool isRollBack = false;
                            if (queryResult.ErrorHint == null && queryResult.Result.TryGetValue(queryCommandSql, out Dictionary<string, List<object>>? data) &&
                                data.TryGetValue("command_name", out List<object>? commands) &&
                                commands.Count != 0)
                            {
                                Logger.Information("execute command update");
                                if (DatabaseSeriver.LocalDBQueryFree(updateCommandSql) == null)
                                {
                                    isRollBack = true;
                                }
                                Logger.DebudElite($"info update to sql success, where index {ChangeIndex}");
                            }
                            else
                            {
                                if (DatabaseSeriver.LocalDBQueryFree(insertCommandSql) == null)
                                {
                                    isRollBack = true;
                                }
                                else
                                {
                                    Logger.DebudElite($"info write to sql success, where index {ChangeIndex}");
                                }
                            }
                            if (isRollBack)
                            {
                                HoldCommandSectionModel.CommandListItems[ChangeIndex] = new CommandStruct(
                                HoldCommandSectionModel.CommandListItems[ChangeIndex].Command,
                                HoldCommandSectionModel.CommandListItems[ChangeIndex].Duration,
                                HoldCommandSectionModel.CommandListItems[ChangeIndex].Alias,
                                HoldCommandSectionModel.CommandListItems[ChangeIndex].Order); // Rollback Sql
                                Logger.Error($"info write to sql encount error, rollback now, where index {ChangeIndex}");
                            }
                        }
                    }

                }catch (Exception error)
                {
                    Logger.ErrorElite("CommandChangeEvent: ", error.Message);
                }
            }
            ModelUpdate(1);
        }

        // 指令执行
        public void CommandWriteEvent(object? param)
        {
            PowerPlantServer.Write(HoldCommandSectionModel.CommandSelectionsCache);
        }

        // 指令选中模式
        public void CommandModeEvent(object? param)
        {
            switch (HoldPublicSectionModel.ListBoxModeName)
            {
                case "\ue64b":
                    HoldPublicSectionModel.ListBoxModeName = "\ue653";
                    HoldPublicSectionModel.ListBoxMode = SelectionMode.Extended;
                    break;

                case "\ue653":
                    HoldPublicSectionModel.ListBoxModeName = "\ue64b";
                    HoldPublicSectionModel.ListBoxMode = SelectionMode.Single;
                    break;
            }
            ModelUpdate(2);
            Logger.DebudElite("comamnd listbox mode change, where model: ", HoldPublicSectionModel.ListBoxModeName);
        }

        // 串口连接
        public void ConnectExcuteEvent(object? param)
        {
            try
            {
                if (PowerPlantServer.Action(2).Item1)
                {
                    var _action = PowerPlantServer.Action(0);
                    if (_action.Item1)
                    {
                        HoldConfigSectionModel.ExecuteButtonText = "连接";
                    }
                    else
                    {
                        CustomMessageBox.Show("警告", 1, ["知道了"], _action.Item2);
                    }
                }
                else
                {
                    SaveFromConfig();
                    var _action = PowerPlantServer.Action(1);
                    if (_action.Item1 && string.IsNullOrEmpty(_action.Item2))
                    {
                        Logger.Information("serial open success");
                        HoldConfigSectionModel.ExecuteButtonText = "关闭";
                    }
                    else
                    {
                        CustomMessageBox.Show("警告", 1, ["知道了"], _action.Item2);

                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Error($"serial action enconter error-> {ex.Message}");
            }
            finally
            {
                ModelUpdate();
            }
        }

        // 保存串口连接配置
        public async void SaveFromConfig()
        {
            if (!string.IsNullOrEmpty(ConfigSelectedRecord.Com.PortName) &&
                SerialConfigInfoMap.Com.SerialComNameMap.TryGetValue(ConfigSelectedRecord.Com.PortName, out string? portName) &&
                portName is not null)
            {
                PowerPlantServer.GetSerialPortiInstance().PortName = portName;
                PowerPlantServer.GetSerialPortiInstance().BaudRate = ConfigSelectedRecord.Com.BaudRate;
                PowerPlantServer.GetSerialPortiInstance().DataBits = ConfigSelectedRecord.Com.DataBit;
                PowerPlantServer.GetSerialPortiInstance().Parity = ConfigSelectedRecord.Com.ParityBit;
                PowerPlantServer.GetSerialPortiInstance().StopBits = ConfigSelectedRecord.Com.StopBit;
                PowerPlantServer.GetSerialPortiInstance().Handshake = ConfigSelectedRecord.Com.Handshake;

                if (DatabaseSeriver.GetIdentify())
                {
                    try
                    {
                        if (DatabaseSeriver.GetCloudDB() is not null and Supabase.Client CloudDB)
                        {
                            string Portname = ConfigSelectedRecord.Com.PortName;
                            string Baudrate = ConfigSelectedRecord.Com.BaudRate.GetSafetyChar();
                            string Databits = ConfigSelectedRecord.Com.DataBit.GetSafetyChar();
                            string Stopbits = ConfigSelectedRecord.Com.StopBit.GetSafetyChar();
                            string Paritybits = ConfigSelectedRecord.Com.ParityBit.GetSafetyChar();
                            string Handshake = ConfigSelectedRecord.Com.Handshake.GetSafetyChar();
                            var Query = await CloudDB.From<SerialConfig>().Get();
                            if (Query.Models.Count > 0)
                            {
                                string oldPortname = Query.Models[0].Portname;

                                await CloudDB.From<SerialConfig>()
                                    .Set(x => x.Portname, Portname)
                                    .Set(x => x.Baudrate, Baudrate)
                                    .Set(x => x.Databits, Databits)
                                    .Set(x => x.Stopbits, Stopbits)
                                    .Set(x => x.Paritybits, Paritybits)
                                    .Set(x => x.Handshake, Handshake)
                                    .Where(x => x.Portname == oldPortname)
                                    .Update();
                            }
                            else
                            {
                                var data = new SerialConfig()
                                {
                                    Portname = ConfigSelectedRecord.Com.PortName,
                                    Baudrate = ConfigSelectedRecord.Com.BaudRate.GetSafetyChar(),
                                    Databits = ConfigSelectedRecord.Com.DataBit.GetSafetyChar(),
                                    Stopbits = ConfigSelectedRecord.Com.StopBit.GetSafetyChar(),
                                    Paritybits = ConfigSelectedRecord.Com.ParityBit.GetSafetyChar(),
                                    Handshake = ConfigSelectedRecord.Com.Handshake.GetSafetyChar()
                                };
                                await CloudDB.From<SerialConfig>().Insert(data);
                            }
                        }

                        else
                        {
                            string queryConfigSql = "SELECT port_name FROM serial_config";

                            string updateConfigSql = "UPDATE serial_config SET " +
                                                    $"port_name = '{ConfigSelectedRecord.Com.PortName}'," +
                                                    $"baud_rate = '{ConfigSelectedRecord.Com.BaudRate}'," +
                                                    $"data_bits = '{ConfigSelectedRecord.Com.DataBit}'," +
                                                    $"stop_bits = '{ConfigSelectedRecord.Com.StopBit}'," +
                                                    $"parity_bits = '{ConfigSelectedRecord.Com.ParityBit}'," +
                                                    $"hand_shake = '{ConfigSelectedRecord.Com.Handshake}' ";

                            string insertConfigSql = $"INSERT INTO serial_config VALUES(" +
                                                     $"'{ConfigSelectedRecord.Com.PortName}'," +
                                                     $"'{ConfigSelectedRecord.Com.BaudRate}'," +
                                                     $"'{ConfigSelectedRecord.Com.DataBit}'," +
                                                     $"'{ConfigSelectedRecord.Com.StopBit}'," +
                                                     $"'{ConfigSelectedRecord.Com.ParityBit}'," +
                                                     $"'{ConfigSelectedRecord.Com.Handshake}')";

                            if (await DatabaseSeriver.LocalDBQueryFree(queryConfigSql) is SqliteExceuteResult queryResult &&
                                queryResult.ErrorHint == null &&
                                queryResult.Result.TryGetValue(queryConfigSql, out Dictionary<string, List<object>>? data) &&
                                data.Count != 0)
                            {
                                await DatabaseSeriver.LocalDBQueryFree(updateConfigSql);
                            }
                            else
                            {
                                Logger.Information("execute config insert");
                                await DatabaseSeriver.LocalDBQueryFree(insertConfigSql);
                            }
                        }
                    }
                    catch (Exception error)
                    {
                        Logger.ErrorElite($"config serialport save {error.Message}");
                    }
                }
            }      
        }

        //数据重加载专用方法
        public void DBconnectStart()
        {
            if (DatabaseSeriver.GetIdentify())
            {
                DBconnectWatch.Restart();
                CloudDBTimer.Start();
            }
            else
            {
                DBconnectWatch.Restart();
                LoaclDBTimer.Start();
            }
        }

        // 统一加载(云数据库)
        public async void CloudReadyWork(object? sender, EventArgs e)
        {
            if (DatabaseSeriver.GetCloudDB() is not null and Supabase.Client CloudDB)
            {
                CloudDBTimer.Stop();
                PublicConnectEnable = true;

                try
                {
                    var parallelOptions = new ParallelOptions
                    {
                        MaxDegreeOfParallelism = 3
                    };
                    List<Action> Tasks = [GetSerialComInfo, GetCommandInfo];
                    await Task.Run(() =>
                    {
                        Parallel.ForEachAsync(Tasks, parallelOptions, (task, cancellationToken) =>
                        {
                            task();
                            return ValueTask.CompletedTask;
                        });
                    });
                    SerialMonitor();
                }
                catch (Exception error)
                {
                    Logger.DebudElite("ReadyWork encount error: ", error.Message);
                }
            }
            if (DBconnectWatch.ElapsedMilliseconds > DBconnectTimeOut)
            {
                DBconnectWatch.Restart();
                DBconnectWatch.Stop();
                CloudDBTimer.Stop();
                LoaclDBTimer.Start();
                Logger.DebudElite("activity cloud ready task timeout");
            }
        }

        // 统一加载(本地数据库)
        public async void LocalReadyWork(object? sender, EventArgs e)
        {
            if (DatabaseSeriver.LocalDBSurvival(DBreserveInfo.LocalDBName))
            {
                LoaclDBTimer.Stop();
                PublicConnectEnable = true;
                try
                {
                    var parallelOptions = new ParallelOptions
                    {
                        MaxDegreeOfParallelism = 3
                    };

                    List<Action> Tasks = [TableCreate, GetSerialComInfo, GetCommandInfo];
                    await Task.Run(() =>
                    {
                        Parallel.ForEachAsync(Tasks, parallelOptions, (task, cancellationToken) =>
                        {
                            task();
                            return ValueTask.CompletedTask;
                        });
                    });
                    SerialMonitor();
                }
                catch (Exception error)
                {
                    Logger.DebudElite("ReadyWork encount error: ", error.Message);
                }
            }
            if (DBconnectWatch.ElapsedMilliseconds > DBconnectTimeOut)
            {
                DBconnectWatch.Restart();
                DBconnectWatch.Stop();
                LoaclDBTimer.Stop();
                CloudDBTimer.Start();
                Logger.DebudElite("activity local ready task timeout");
            }
        }

        // 加载上一次的串口配置
        private async void GetSerialComInfo()
        {
            string sqlPortName = string.Empty;
            string sqlBaudBit = string.Empty;
            string sqlDataBit = string.Empty;
            string sqlStopBit = string.Empty;
            string sqlParityBit = string.Empty;
            string sqlHandShake = string.Empty;

            void dispose(bool valid)
            {
                if (valid)
                {
                    if (!string.IsNullOrEmpty(sqlPortName) && SerialConfigInfoMap.Com.SerialComNameMap.TryGetValue(sqlPortName, out string? realname))
                    {
                        if (realname != null)
                        {
                            HoldConfigSectionModel.SelectedSerialProt = sqlPortName;
                            ConfigSelectedRecord.Com.PortName = sqlPortName;
                        }
                    }
                    else
                    {
                        if (HoldConfigSectionModel.SerialProts.Count > 0) HoldConfigSectionModel.SelectedSerialProt = HoldConfigSectionModel.SerialProts[0];
                    }

                    if (!string.IsNullOrEmpty(sqlBaudBit) && SerialConfigInfoMap.Com.SerialComBaudMap.TryGetValue(sqlBaudBit, out var realbaud))
                    {
                        HoldConfigSectionModel.SelectedBaudRate = sqlBaudBit;
                        ConfigSelectedRecord.Com.BaudRate = realbaud;
                    }
                    else
                    {
                        if (HoldConfigSectionModel.BaudRates.Count > 0) HoldConfigSectionModel.SelectedBaudRate = HoldConfigSectionModel.BaudRates[0];
                    }

                    if (!string.IsNullOrEmpty(sqlDataBit) && SerialConfigInfoMap.Com.SerialComDataMap.TryGetValue(sqlDataBit, out var realdata))
                    {
                        HoldConfigSectionModel.SelectedDataBit = sqlDataBit;
                        ConfigSelectedRecord.Com.DataBit = realdata;
                    }
                    else
                    {
                        if (HoldConfigSectionModel.DataBits.Count > 0) HoldConfigSectionModel.SelectedDataBit = HoldConfigSectionModel.DataBits[0];
                    }

                    if (!string.IsNullOrEmpty(sqlStopBit) && SerialConfigInfoMap.Com.SerialComStopMap.TryGetValue(sqlStopBit, out var realstop))
                    {
                        HoldConfigSectionModel.SelectedStopBit = sqlStopBit;
                        ConfigSelectedRecord.Com.StopBit = realstop;
                    }
                    else
                    {
                        if (HoldConfigSectionModel.StopBits.Count > 0) HoldConfigSectionModel.SelectedStopBit = HoldConfigSectionModel.StopBits[0];
                    }

                    if (!string.IsNullOrEmpty(sqlParityBit) && SerialConfigInfoMap.Com.SerialComParityMap.TryGetValue(sqlPortName, out var realparity))
                    {
                        HoldConfigSectionModel.SelectedParityBit = sqlParityBit;
                        ConfigSelectedRecord.Com.ParityBit = realparity;
                    }
                    else
                    {
                        if (HoldConfigSectionModel.ParityBits.Count > 0) HoldConfigSectionModel.SelectedParityBit = HoldConfigSectionModel.ParityBits[0];
                    }

                    if (!string.IsNullOrEmpty(sqlHandShake) && SerialConfigInfoMap.Com.SerialComHandShakeMap.TryGetValue(sqlHandShake, out var realhand))
                    {
                        HoldConfigSectionModel.SelectedHandShake = sqlHandShake;
                        ConfigSelectedRecord.Com.Handshake = realhand;
                    }
                    else
                    {
                        if (HoldConfigSectionModel.HandShakes.Count > 0) HoldConfigSectionModel.SelectedHandShake = HoldConfigSectionModel.HandShakes[0];
                    }
                }
                else
                {
                    ConfigSelectedRecord.Com.PortName = HoldConfigSectionModel.SerialProts[0];
                    ConfigSelectedRecord.Com.BaudRate = SerialConfigInfoMap.Com.SerialComBaudMap[HoldConfigSectionModel.BaudRates[0]];
                    ConfigSelectedRecord.Com.DataBit = SerialConfigInfoMap.Com.SerialComDataMap[HoldConfigSectionModel.DataBits[0]];
                    ConfigSelectedRecord.Com.ParityBit = SerialConfigInfoMap.Com.SerialComParityMap[HoldConfigSectionModel.ParityBits[0]];
                    ConfigSelectedRecord.Com.StopBit = SerialConfigInfoMap.Com.SerialComStopMap[HoldConfigSectionModel.StopBits[0]];
                    ConfigSelectedRecord.Com.Handshake = SerialConfigInfoMap.Com.SerialComHandShakeMap[HoldConfigSectionModel.HandShakes[0]];

                    if (HoldConfigSectionModel.SerialProts.Count > 0) HoldConfigSectionModel.SelectedSerialProt = HoldConfigSectionModel.SerialProts[0];
                    if (HoldConfigSectionModel.BaudRates.Count > 0) HoldConfigSectionModel.SelectedBaudRate = "115200";
                    if (HoldConfigSectionModel.DataBits.Count > 0) HoldConfigSectionModel.SelectedDataBit = "8";
                    if (HoldConfigSectionModel.StopBits.Count > 0) HoldConfigSectionModel.SelectedStopBit = "Two";
                    if (HoldConfigSectionModel.ParityBits.Count > 0) HoldConfigSectionModel.SelectedParityBit = "None";
                    if (HoldConfigSectionModel.HandShakes.Count > 0) HoldConfigSectionModel.SelectedHandShake = "None";
                }
            }

            ManagementObjectSearcher Cominfos = new(@"SELECT * FROM Win32_PnPEntity WHERE NAME LIKE '%COM%'");
            HoldConfigSectionModel.SerialProts = [.. Cominfos.Com(Extendsion.CollectionType.t_ObservableCollection)];
            HoldConfigSectionModel.DataBits = SerialServer.ReceiveSerialInfo(EmSerialInfoType.Databits);
            HoldConfigSectionModel.StopBits = SerialServer.ReceiveSerialInfo(EmSerialInfoType.StopBits);
            HoldConfigSectionModel.ParityBits = SerialServer.ReceiveSerialInfo(EmSerialInfoType.ParityBits);
            HoldConfigSectionModel.BaudRates = SerialServer.ReceiveSerialInfo(EmSerialInfoType.BundRate);
            HoldConfigSectionModel.HandShakes = SerialServer.ReceiveSerialInfo(EmSerialInfoType.HandShakes);
            if (DatabaseSeriver.GetIdentify())
            {
                if (DatabaseSeriver.GetCloudDB() is not null and Supabase.Client CloudDB)
                {
                    var queryResult = await CloudDB.From<SerialConfig>().Get();
                    
                    if (queryResult.Model is not null)
                    {
                        sqlPortName = queryResult.Model.Portname;
                        sqlBaudBit = queryResult.Model.Baudrate;
                        sqlDataBit = queryResult.Model.Databits;
                        sqlStopBit = queryResult.Model.Stopbits;
                        sqlParityBit = queryResult.Model.Paritybits;
                        sqlHandShake = queryResult.Model.Handshake;
                    }
                }
            }
            else
            {
                if (DatabaseSeriver.LocalDBSurvival(DBreserveInfo.LocalDBName))
                {
                    string queryConfigSql = "SELECT * FROM serial_config";
                    var queryResult = await DatabaseSeriver.LocalDBQueryFree(queryConfigSql);

                    await Task.Run(() =>
                    {
                        Parallel.Invoke(() =>
                        {
                            if (queryResult.ErrorHint == null && queryResult.Result.TryGetValue(queryConfigSql, out Dictionary<string, List<object>>? Data))
                            {
                                sqlPortName = Data["port_name"].GetSafetyChar(0);
                                sqlBaudBit = Data["baud_rate"].GetSafetyChar(0);
                                sqlDataBit = Data["data_bits"].GetSafetyChar(0);
                                sqlStopBit = Data["stop_bits"].GetSafetyChar(0);
                                sqlParityBit = Data["parity_bits"].GetSafetyChar(0);
                                sqlHandShake = Data["hand_shake"].GetSafetyChar(0);
                            }
                        });
                    });
                }
            }

            dispose(!string.IsNullOrEmpty(sqlPortName));
            ModelUpdate();
        }

        //创建sqlite数据库
        public async void TableCreate()
        {
            await Task.Run(async () =>
            {
                string verityTableSql = "select name from sqlite_master where type='table'";
                var sqltablecreate = await DatabaseSeriver.LocalDBQueryFree(verityTableSql);
                List<string> unexistsTables = [];
                foreach (var key in HoldConfigSectionModel.TableReserveDuty.Keys)
                {
                    if (sqltablecreate.ErrorHint == null && sqltablecreate.Result.TryGetValue(verityTableSql, out var keyValues))
                    {
                        if (keyValues.TryGetValue("name", out List<object>? tables) && tables is not null)
                        {
                            if (!tables.Contains(key)) unexistsTables.Add(HoldConfigSectionModel.TableReserveDuty[key]);
                        }
                        else
                        {
                            unexistsTables.Add(HoldConfigSectionModel.TableReserveDuty[key]);
                        }
                    }
                    else
                    {
                        unexistsTables.Add(HoldConfigSectionModel.TableReserveDuty[key]);
                    }
                }
                if (await DatabaseSeriver.LocalDBQuery(unexistsTables) is SqliteExceuteResult result &&
                    result.ErrorHint == null)
                {
                    Logger.Debug("dispose sql of table create");
                }
                else
                {
                    Logger.Error("table create fail");
                }
            }).ConfigureAwait(false);
        }

        // 加载指令数据
        public async void GetCommandInfo()
        {
            await Task.Delay(1500);
            if (DatabaseSeriver.GetIdentify())
            {
                if (DatabaseSeriver.GetCloudDB() is not null and Supabase.Client CloudDB)
                {
                    var queryResult = await CloudDB.From<SerialCommand>().Get();
                    System.Windows.Application.Current.Dispatcher.Invoke(() =>
                    {
                        HoldCommandSectionModel.CommandListItems.Clear();
                    });
                    foreach (var model in queryResult.Models)
                    {
                        string command_name = model.Commandname;
                        string command_alias = model.Commandalias;
                        string command_interval = model.Commandinterval;

                        if (int.TryParse(command_interval, out int interval) && !string.IsNullOrEmpty(command_name))
                        {
                            await System.Windows.Application.Current.Dispatcher.InvokeAsync(() =>
                            {
                                HoldCommandSectionModel.CommandListItems.Add(new CommandStruct(command_name, interval, command_alias));
                            });
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }
            else
            {
                if (DatabaseSeriver.LocalDBSurvival(DBreserveInfo.LocalDBName))
                {
                    string queryConfigSql = "SELECT * FROM serial_command";
                    var queryResult = await DatabaseSeriver.LocalDBQueryFree(queryConfigSql);
                    await Task.Delay(40).ContinueWith(_ =>
                    {
                        if (queryResult.ErrorHint == null && queryResult.Result.TryGetValue(queryConfigSql, out Dictionary<string, List<object>>? CommandDict))
                        {
                            System.Windows.Application.Current.Dispatcher.Invoke(() =>
                            {
                                HoldCommandSectionModel.CommandListItems.Clear();
                            });
                            int indexof = 0;
                            foreach (var name in CommandDict["command_name"])
                            {
                                string command_name = name.ToString() ?? string.Empty;
                                string command_alias = CommandDict["command_alias"].GetSafetyChar(indexof);
                                string command_interval = CommandDict["command_interval"].GetSafetyChar(indexof);

                                if (int.TryParse(command_interval, out int interval) && !string.IsNullOrEmpty(command_name))
                                {
                                    System.Windows.Application.Current.Dispatcher.InvokeAsync(() =>
                                    {
                                        HoldCommandSectionModel.CommandListItems.Add(new CommandStruct(command_name, interval, command_alias));
                                    });
                                }
                                else
                                {
                                    break;
                                }
                                indexof++;
                            }
                        }
                    });
                }
            }
        }

        public async void SerialMonitor()
        {
            await Task.Run(() =>
            {
                Parallel.Invoke(() =>
                {
                    PowerPlantServer.Moniter(() =>
                    {
                         GetSerialComInfo();
                    }, 1, true);
                },

                () =>
                {
                    PowerPlantServer.Moniter(() =>
                    {
                        GetSerialComInfo();
                    }, 0, true);
                });
            });
        }

        public void ConfigProperyChangeEvent(object? objects)
        {
            bool isOpen = PowerPlantServer.Action(2).Item1;
            if (isOpen) PowerPlantServer.Action(0);

            ConfigSelectedRecord.Com.PortName = HoldConfigSectionModel.SelectedSerialProt;

            if (SerialConfigInfoMap.Com.SerialComBaudMap.TryGetValue(HoldConfigSectionModel.SelectedBaudRate, out int baud))
            {
                ConfigSelectedRecord.Com.BaudRate = baud;
                if (isOpen) PowerPlantServer.GetSerialPortiInstance().BaudRate = baud;
            }
            if (SerialConfigInfoMap.Com.SerialComDataMap.TryGetValue(HoldConfigSectionModel.SelectedDataBit, out int data))
            {
                ConfigSelectedRecord.Com.DataBit = data;
                if (isOpen) PowerPlantServer.GetSerialPortiInstance().DataBits = data;
            }
            if (SerialConfigInfoMap.Com.SerialComStopMap.TryGetValue(HoldConfigSectionModel.SelectedStopBit, out StopBits stop))
            {
                ConfigSelectedRecord.Com.StopBit = stop;
                if (isOpen) PowerPlantServer.GetSerialPortiInstance().StopBits = stop;
            }
            if (SerialConfigInfoMap.Com.SerialComParityMap.TryGetValue(HoldConfigSectionModel.SelectedParityBit, out Parity parity))
            {
                ConfigSelectedRecord.Com.ParityBit = parity;
                if (isOpen) PowerPlantServer.GetSerialPortiInstance().Parity = parity;
            }
            if (SerialConfigInfoMap.Com.SerialComHandShakeMap.TryGetValue(HoldConfigSectionModel.SelectedHandShake, out Handshake hand))
            {
                ConfigSelectedRecord.Com.Handshake = hand;
                if (isOpen) PowerPlantServer.GetSerialPortiInstance().Handshake = hand;
            }

            if (DatabaseSeriver.LocalDBSurvival(DBreserveInfo.LocalDBName))
            {
                SaveFromConfig();
            }
            if (isOpen)
            {
                PowerPlantServer.Action(1);
            }
        }

        public void ModelUpdate(int type = 0)
        {
            switch (type)
            {
                case 0:
                    propertyChangeSend(nameof(HoldConfigSectionModel));
                    break;

                case 1:
                    propertyChangeSend(nameof(HoldCommandSectionModel));
                    break;

                case 2:
                    propertyChangeSend(nameof(HoldPublicSectionModel));
                    break;
            }
        }
    }
}
